package com.example.demo.server;

import com.example.demo.cache.ChannelMap;
import com.example.demo.model.Result;
import com.example.demo.model.Tenant;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
import lombok.extern.slf4j.Slf4j;

/**
 * @ClassName: NettyServerHandler
 * @Author: huangzf
 * @Date: 2018/9/25 15:44
 * @Description:
 */
@Slf4j
public class NettyServerHandler extends SimpleChannelInboundHandler {

    private CountDownLatch latch;

    /**
     * 消息的唯一ID
     */
    private String unidId = "";
    /**
     * 同步标志
     */
    private int rec;
    /**
     * 客户端返回的结果
     */
    private Result result;
    /**
     * 心跳丢失次数
     */
    private int counter = 0;


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("Client say : " + msg.toString());
        if(msg instanceof Tenant){
            ChannelMap.setChannel(((Tenant) msg).getTenantId(),ctx.channel());
            ChannelMap.setChannelLock(((Tenant) msg).getTenantId(),new ReentrantLock());
        }

        counter = 0;
        if(rec == 1  && msg instanceof Result){
            Result re = (Result) msg;
            //校验返回的信息是否是同一个信息
            if (unidId.equals(re.getUniId())){
                latch.countDown();//消息返回完毕，释放同步锁，具体业务需要判断指令是否匹配
                rec = 0;
                result = re;
            }

        }


    }


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("RemoteAddress : " + ctx.channel().remoteAddress().toString()+ " active !");
        super.channelActive(ctx);
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state().equals(IdleState.READER_IDLE)){
                // 空闲40s之后触发 (心跳包丢失)
                if (counter >= 3) {
                    // 连续丢失3个心跳包 (断开连接)
                    ctx.channel().close().sync();
                    log.error("已与"+ctx.channel().remoteAddress()+"断开连接");
                    System.out.println("已与"+ctx.channel().remoteAddress()+"断开连接");
                } else {
                    counter++;
                    log.debug(ctx.channel().remoteAddress() + "丢失了第 " + counter + " 个心跳包");
                    System.out.println("丢失了第 " + counter + " 个心跳包");
                }
            }

        }
    }

    public void resetSync(CountDownLatch latch, int rec) {
        this.latch = latch;
        this.rec = rec;
    }

    public void setUnidId(String s){
        this.unidId = s;
    }

    public Result getResult() {
        return result;
    }
}
